﻿using System;
using System.Collections;
using System.Configuration.Install;
using System.ServiceProcess;
using System.Threading;

static class Program
{
    #region Static Methods

    /// <summary>
    /// This method is called when the Program starts.
    /// </summary>
    /// <param name="args">Start arguments.</param>
    /// <returns>An integer with value 0 if there are no errors; else it will return -1.</returns>
    private static int Main(string[] args)
    {
        bool throwError = false;
        try
        {
            if (args.Length > 0)
            {
                switch (args[0])
                {
                    case "-i":
                    case "-install":
                        /* Installs it as a Windows service. */
                        Program.Install(args);
                        break;

                    case "-u":
                    case "-uninstall":
                        /* Uninstalls the Windows service. */
                        Program.Uninstall(args);
                        break;

                    case "-c":
                    case "-console":
                        /* Runs the application on console mode. */
                        Program.RunConsoleMode();
                        break;

                    default:
                        throw new Exception(string.Format("Argument not expected: {0}", args[0]));
                }
            }
            else
            {
                /* If no commands passed just runs the application. */
                throwError = true;

                ServiceBase.Run(new ServiceBase[] { new Service() });

                throwError = false;
            }

            return 0;
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex.Message);

            if (throwError == true)
                throw ex;

            return -1;
        }
    }

    /// <summary>
    /// Installs the windows service.
    /// </summary>
    /// <param name="args">Install arguments.</param>
    private static void Install(string[] args)
    {
        try
        {
            Console.WriteLine("Installing service");

            /* The AssemblyInstaller class will be implemented to load the CustomInstaller class to install the service. */
            using (AssemblyInstaller inst = new AssemblyInstaller(typeof(Program).Assembly, args))
            {
                /* Initializes an IDictionary object wich will have the state of the procedure. */
                IDictionary state = new Hashtable();
                inst.UseNewContext = true;

                try
                {
                    /* Install and commit installer state. */
                    inst.Install(state);
                    inst.Commit(state);
                }
                catch
                {
                    try
                    {
                        /* Rollback all operations made if errors have been thrown. */
                        inst.Rollback(state);
                    }
                    catch { }
                    throw;
                }
            }
        }
        catch (Exception ex) { Console.Error.WriteLine(ex.Message); }
    }
    /// <summary>
    /// Runs the application in console mode.
    /// </summary>
    private static void RunConsoleMode()
    {
        try
        {
            //Initialize a new QualityFilesService instance. Then start it and wait for the use topress any key to stop it.
            Service service = new Service();

            Console.WriteLine("Starting in console mode...");

            service.Start();

            Console.WriteLine(string.Format("'{0}' running. Press any key to stop.", service.DisplayName));

            //Waits for the user to press any key to stop the application.
            while (true)
            {
                if (Console.KeyAvailable)
                {
                    service.Stop();
                    break;
                }

                Thread.Sleep(100);
            }

            Console.WriteLine(string.Format("'{0}' stopped.", service.DisplayName));
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex.Message);
            Console.Error.WriteLine(ex.StackTrace);

            Console.WriteLine("");
            Console.WriteLine("Press any key to exit.");

            //Waits for the user to press any key to stop the application.
            while (true)
            {
                if (Console.KeyAvailable)
                    break;

                Thread.Sleep(100);
            }
        }
    }

    /// <summary>
    /// Uninstalls the QualityFilesService.
    /// </summary>
    /// <param name="args">Uninstall arguments.</param>
    private static void Uninstall(string[] args)
    {
        try
        {
            Console.WriteLine("Uninstalling service");

            /* The AssemblyInstaller class will be implemented to load the CustomInstaller class to install the service. */
            using (AssemblyInstaller inst = new AssemblyInstaller(typeof(Program).Assembly, args))
            {
                /* Initializes an IDictionary object wich will have the state of the procedure. */
                IDictionary state = new Hashtable();
                inst.UseNewContext = true;

                try
                {
                    inst.Uninstall(state);
                }
                catch
                {
                    try
                    {
                        /* Rollback all operations made if errors have been thrown. */
                        inst.Rollback(state);
                    }
                    catch { }
                    throw;
                }
            }
        }
        catch (Exception ex) { Console.Error.WriteLine(ex.Message); }
    }

    #endregion
}
